package org.yu.register.machine;

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.Connection;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.yu.api.util.ITickable;

import javax.annotation.Nonnull;

public class StoveBlockEntity extends BlockEntity implements ITickable {
    protected int burnTimes=0;
    protected boolean open =true;

    protected final ItemStackHandler itemStackHandler=new ItemStackHandler(1){
        @Override
        protected void onContentsChanged(int slot) {
            StoveBlockEntity.this.setChanged();
            if(level!=null)
                level.sendBlockUpdated(getBlockPos(),getBlockState(),getBlockState().setValue(StoveBlock.LIT,isOpen()),3);
        }

        @Override
        public boolean isItemValid(int slot, @Nonnull ItemStack stack) {
            return ForgeHooks.getBurnTime(stack, RecipeType.SMELTING)>0;
        }
    };
    public StoveBlockEntity(BlockEntityType<?> pType, BlockPos pWorldPosition, BlockState pBlockState) {
        super(pType, pWorldPosition, pBlockState);
    }
    @NotNull
    @Override
    public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
        if(cap== CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
            return LazyOptional.of(()->itemStackHandler).cast();
        return super.getCapability(cap, side);
    }
    public boolean isOpen(){
        return open&&burnTimes>0;
    }
    @Override
    public void tick() {
        if(level instanceof ServerLevel){
            var lit=getBlockState().getValue(StoveBlock.LIT);
            if(burnTimes<=0){
                var item=itemStackHandler.getStackInSlot(0);
                var flue=ForgeHooks.getBurnTime(item,RecipeType.SMELTING);
                if(flue>0&&open){
                    item.shrink(1);
                    burnTimes+=flue;
                }
            }else {
                if(open) {
                    burnTimes--;
                   if (!lit) level.setBlock(getBlockPos(), getBlockState().setValue(StoveBlock.LIT, true), 3);
                }else {
                    level.setBlock(getBlockPos(),getBlockState().setValue(StoveBlock.LIT,false),3);
                }
            }
            if(lit&&burnTimes<=0)level.setBlock(getBlockPos(),getBlockState().setValue(StoveBlock.LIT,false),3);
        }
    }
    @Override
    public void load(@Nonnull CompoundTag pTag) {
        super.load(pTag);
        itemStackHandler.deserializeNBT(pTag.getCompound("Item"));
        if(pTag.contains("Open"))
            open=pTag.getBoolean("Open");
        burnTimes=pTag.getInt("BurnTimes");
    }

    @Override
    protected void saveAdditional(@Nonnull CompoundTag pTag) {
        super.saveAdditional(pTag);
        pTag.put("Item",itemStackHandler.serializeNBT());
        pTag.putBoolean("Open",open);
        pTag.putInt("BurnTimes",burnTimes);
    }

    @Nullable
    @Override
    public Packet<ClientGamePacketListener> getUpdatePacket() {
        return ClientboundBlockEntityDataPacket.create(this);
    }

    @Override
    public void handleUpdateTag(CompoundTag pTag) {
        super.handleUpdateTag(pTag);
        itemStackHandler.deserializeNBT(pTag.getCompound("Item"));
    }

    @NotNull
    @Override
    public CompoundTag getUpdateTag() {
        var pTag=super.getUpdateTag();
        pTag.put("Item",itemStackHandler.serializeNBT());
        return pTag;
    }

    @Override
    public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt) {
        this.handleUpdateTag(pkt.getTag());
    }

    public void setOpen(boolean flag) {
        this.open=flag;
        if(level!=null)
            level.sendBlockUpdated(getBlockPos(),getBlockState(),getBlockState().setValue(StoveBlock.LIT,isOpen()),3);
    }
}
